package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.wordmemorize.common.annotation.OperateLog;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.LevelConverter;
import com.cskaoyan.wordmemorize.dao.entity.LevelDO;
import com.cskaoyan.wordmemorize.dao.mapper.LevelMapper;
import com.cskaoyan.wordmemorize.dto.admin.DeleteLevelOperateDTO;
import com.cskaoyan.wordmemorize.dto.admin.LevelDTO;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.request.BatchDeleteCommand;
import com.cskaoyan.wordmemorize.request.LevelCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.service.LevelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 等级服务实现类
 */
@Service
@Slf4j
public class LevelServiceImpl extends ServiceImpl<LevelMapper, LevelDO> implements LevelService {

    @Autowired
    private LevelConverter levelConverter;


    /**
     * 添加等级(后台等级权限管理-等级管理)
     *
     * @param command 等级命令
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "等级", operateType = 1)
    public void addLevel(LevelCommand command) {
        // 检查等级值是否已存在
        LambdaQueryWrapper<LevelDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LevelDO::getLevelValue, command.getLevelValue())
                .eq(LevelDO::getIsDeleted, 0);

        if (count(queryWrapper) > 0) {
            throw new BusinessException("等级值已存在", 500);
        }

        // 转换为DO并保存
        LevelDO levelDO = levelConverter.levelCommandToLevelDO(command);

        // 保存记录
        boolean success = save(levelDO);

        if (!success) {
            throw new BusinessException("添加等级失败", 500);
        }
    }

    /**
     * 修改等级(后台等级权限管理-等级管理)
     *
     * @param command 等级命令
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "等级", operateType = 2)
    public void updateLevel(LevelCommand command) {
        // 检查等级是否存在
        if (!StringUtils.hasText(command.getId())) {
            throw new BusinessException("参数错误", 500);
        }

        LevelDO existLevel = getById(Long.valueOf(command.getId()));
        if (existLevel == null || existLevel.getIsDeleted() == 1) {
            throw new BusinessException("等级不存在", 500);
        }

        // 检查等级值是否已被其他记录使用
        if (command.getLevelValue() != null && !command.getLevelValue().equals(existLevel.getLevelValue())) {
            LambdaQueryWrapper<LevelDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(LevelDO::getLevelValue, command.getLevelValue())
                    .eq(LevelDO::getIsDeleted, 0)
                    .ne(LevelDO::getId, Long.valueOf(command.getId()));

            if (count(queryWrapper) > 0) {
                throw new BusinessException("等级值已存在", 500);
            }
        }

        // 转换为DO并更新
        LevelDO levelDO = levelConverter.levelCommandToLevelDO(command);

        // 更新记录
        boolean success = updateById(levelDO);

        if (!success) {
            throw new BusinessException("更新等级失败", 500);
        }
    }

    /**
     * 分页查询等级(后台等级权限管理-等级管理)
     *
     * @param request 分页请求
     * @return 等级分页列表
     */
    @Override
    public PageDTO<LevelDTO> getLevelList(PageRequest request) {
        log.info("开始查询等级列表，关键字: {}", request.getKeyword());

        // 创建分页对象
        Page<LevelDO> page = new Page<>(request.getPageNum(), request.getCount());

        // 创建查询条件
        LambdaQueryWrapper<LevelDO> queryWrapper = new LambdaQueryWrapper<>();

        // 如果有关键词，则添加模糊查询条件——等级名称
        if (StringUtils.hasText(request.getKeyword())) {
            log.info("添加关键字查询条件: {}", request.getKeyword());
            queryWrapper.like(LevelDO::getLevelName, request.getKeyword());
        }

        // 只查询未删除的记录
        queryWrapper.eq(LevelDO::getIsDeleted, 0);

        // 按等级值升序排序
        queryWrapper.orderByAsc(LevelDO::getLevelValue);

        // 执行分页查询
        Page<LevelDO> resultPage = page(page, queryWrapper);
        log.info("查询结果总数: {}", resultPage.getTotal());

        // 转换为DTO列表
        List<LevelDTO> levelDTOs = resultPage.getRecords().stream()
                .map(levelConverter::levelDOToLevelDTO)
                .collect(Collectors.toList());

        // 构建分页DTO并返回
        PageDTO<LevelDTO> pageDTO = new PageDTO<>();
        pageDTO.setPageList(levelDTOs);
        pageDTO.setTotalCount(resultPage.getTotal());

        log.info("返回结果数量: {}", levelDTOs.size());
        return pageDTO;
    }

    /**
     * 删除等级(后台等级权限管理-等级管理)
     *
     * @param id 等级ID
     * @return 删除操作日志
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "等级", operateType = 3)
    public DeleteLevelOperateDTO deleteLevel(Long id) {
        log.info("开始删除等级，ID: {}", id);

        // 检查等级是否存在
        LevelDO levelDO = getById(id);
        if (levelDO == null || levelDO.getIsDeleted() == 1) {
            log.error("等级不存在或已删除，ID: {}", id);
            throw new BusinessException("等级不存在", 500);
        }

        // 保存原始数据供返回
        LevelDO originalDO = new LevelDO();
        org.springframework.beans.BeanUtils.copyProperties(levelDO, originalDO);

        // 使用UpdateWrapper明确指定要更新的字段
        LambdaUpdateWrapper<LevelDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(LevelDO::getId, id)
                .set(LevelDO::getIsDeleted, 1);

        boolean success = update(null, updateWrapper);
        log.info("删除等级结果: {}, ID: {}", success, id);

        if (!success) {
            log.error("删除等级失败，ID: {}", id);
            throw new BusinessException("删除等级失败", 500);
        }

        // 检查是否删除成功
        LevelDO checkDO = getById(id);
        if (checkDO != null && checkDO.getIsDeleted() == 0) {
            log.error("删除后检查失败，等级仍然存在，ID: {}", id);
            throw new BusinessException("删除等级失败", 500);
        }

        // 返回删除操作日志
        return levelConverter.levelDOToDeleteLevelOperateDTO(originalDO);
    }

    /**
     * 批量删除等级(后台等级权限管理-等级管理)
     *
     * @param command 批量删除命令
     * @return 删除操作日志列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperateLog(dateType = "等级", operateType = 4)
    public List<DeleteLevelOperateDTO> deleteLevels(BatchDeleteCommand command) {
        log.info("开始批量删除等级，IDs: {}", command.getIds());

        // 检查参数
        if (command.getIds() == null || command.getIds().isEmpty()) {
            log.error("批量删除参数错误，空的ID列表");
            throw new BusinessException("参数错误", 500);
        }

        // 获取要删除的等级列表
        List<Long> idList = command.getIds().stream()
                .map(Long::valueOf)
                .collect(Collectors.toList());

        List<LevelDO> levelDOList = listByIds(idList);
        log.info("找到的等级数量: {}", levelDOList.size());

        // 过滤出未删除的等级
        List<LevelDO> originalList = new ArrayList<>(levelDOList);
        levelDOList = levelDOList.stream()
                .filter(level -> level.getIsDeleted() == 0)
                .toList();

        if (levelDOList.isEmpty()) {
            log.error("没有找到要删除的等级，所有等级可能已被删除");
            throw new BusinessException("没有找到要删除的等级", 500);
        }

        // 使用UpdateWrapper批量更新
        LambdaUpdateWrapper<LevelDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(LevelDO::getId, idList)
                .set(LevelDO::getIsDeleted, 1);

        boolean success = update(null, updateWrapper);
        log.info("批量删除结果: {}", success);

        if (!success) {
            log.error("批量删除等级失败");
            throw new BusinessException("批量删除等级失败", 500);
        }

        // 检查是否删除成功
        LambdaQueryWrapper<LevelDO> checkWrapper = new LambdaQueryWrapper<>();
        checkWrapper.in(LevelDO::getId, idList)
                .eq(LevelDO::getIsDeleted, 0);

        long count = count(checkWrapper);
        if (count > 0) {
            log.error("有{}条记录未被成功删除", count);
            throw new BusinessException("部分等级删除失败", 500);
        }

        log.info("批量删除等级成功，共{}条", levelDOList.size());

        // 返回删除操作日志列表
        return levelConverter.levelDOsToDeleteLevelOperateDTOs(originalList);
    }
}
